#pragma once
#include"Common.hpp"
#include"Channel.hpp"
#include"TcpSocket.hpp"
#include"Buffer.hpp"
#include"EventLoop.hpp"

#define MAX_BUFFER_SIZE 65530
typedef enum
{
    DISCONNECTED,
    CONNECTING,
    CONNECTED,
    DISCONNECTING
} ConnectionStatu;
class Connection;
using ConnectionPtr = std::shared_ptr<Connection>;
class Connection : public std::enable_shared_from_this<Connection>
{
private:
    // 一个连接应该有的成员
    uint64_t _con_id;               // 连接标识符
    Channel _channel;               // 事件监控
    int _sockfd;                    // 套接字fd
    ConnectionStatu _statu;         // 连接的状态
    TcpSocket _socket;              // 收发数据的套接字
    Buffer _send_buffer;            // 发送缓冲区
    Buffer _recv_buffer;            // 接收缓冲区
    EventLoop *_loop;               // 事件管理模块
    bool _enable_no_active_release; // 是否开启非活跃链接销毁
    Any _context;                   // 用于协议切换
    using ReadEeventCallback_t = std::function<void(const ConnectionPtr &, Buffer *)>;
    using CloseServerCallback_t = std::function<void(const ConnectionPtr &)>;
    using CloseUserCallback_t = std::function<void(const ConnectionPtr &)>;
    using EventCallback_t = std::function<void(const ConnectionPtr &)>;
    using ConnectedCallback_t = std::function<void(const ConnectionPtr &)>;
    ReadEeventCallback_t _read_cb; // 处理读事件
    CloseServerCallback_t _server_close_cb;
    CloseUserCallback_t _user_close_cb;
    EventCallback_t _handle_event_cb;
    ConnectedCallback_t _connected_cb;

private:
    void HandlerRead()
    {
        char buf[MAX_BUFFER_SIZE];
        ssize_t n = _socket.Recv(buf, sizeof(buf) - 1);
        if (n < 0)
        {
            // 说明读取异常!
            return ShutdownInLoop();
        }
        _recv_buffer.WriteAndPush(buf, n);
        // 如果接收缓冲区还有可读数据
        if (_recv_buffer.ReadAbleSize() > 0 && _read_cb)
        {
            _read_cb(shared_from_this(), &_recv_buffer);
        }
        return;
    }
    void HandlerWrite()
    {
        ssize_t n = _socket.Send(_send_buffer.ReadPosition(), _send_buffer.ReadAbleSize());
        if (n < 0)
        {
            // 发送出现异常!
            if (_recv_buffer.ReadAbleSize() > 0 && _read_cb)
            {
                _read_cb(shared_from_this(), &_recv_buffer);
            }
            // 关闭连接
            return Release();
        }
        _send_buffer.MoveReadOffset(n);
        if (_send_buffer.ReadAbleSize() == 0)
        {
            // 没数据关闭写事件监控
            _channel.CloseWriteEventMonitoring();
            if (_statu == DISCONNECTING)
            {
                // 释放连接
                // printf("handlerwrite写入结束，压入释放操作\n");
                return Release(); // 这是第一次压入
            }
        }
        return;
    }
    void HandleClose()
    {
        /*⼀旦连接挂断了，套接字就什么都⼲不了了，因此有数据待处理就处理⼀下，完毕关闭连接*/
        if (_recv_buffer.ReadAbleSize() > 0)
        {
            _read_cb(shared_from_this(), &_recv_buffer);
        }
        return Release();
    }
    // 描述符异常事件处理
    void HandleError()
    {
        return HandleClose();
    }
    void CancelTaskInLoop()
    {
        _enable_no_active_release = false;
        if (_loop->HasTimer(_con_id))
        {
            _loop->TimerCancel(_con_id);
        }
            
    }
    void HandleEvent()
    {
        if (_enable_no_active_release == true)
        {
            _loop->TimerRefresh(_con_id);
        }
        if (_handle_event_cb)
        {
            _handle_event_cb(shared_from_this());
        }
    }
    // 启动非活跃连接销毁
    void EnableInactiveReleaseInLoop(int sec)
    {
        // 1. 将判断标志 _enable_inactive_release 置为true
        _enable_no_active_release = true;
        // 2. 如果当前定时销毁任务已经存在，那就刷新延迟⼀下即可
        if (_loop->HasTimer(_con_id))
        {
            return _loop->TimerRefresh(_con_id);
        }
        // 3. 如果不存在定时销毁任务，则新增
        _loop->TimerAdd(_con_id, sec, std::bind(&Connection::Release, this));
    }
    // 新连接就绪后需要初始化
    void EstablishedInLoop()
    {
        // 1. 修改连接状态； 2. 启动读事件监控； 3. 调⽤回调函数
        _statu = CONNECTED; // 当前函数执⾏完毕，则连接进⼊已完成连接状态
        // ⼀旦启动读事件监控就有可能会⽴即触发读事件，如果这时候启动了⾮活跃连接销毁
        _channel.OpenReadEventMonitoring();
        if (_connected_cb)
        {
            _connected_cb(shared_from_this());
        }
        LOG(DEBUG,"Connection初始化完毕!,id = %d\n",_con_id);
    }

    void SendInLoop(Buffer &buf)
    {
        if (_statu == DISCONNECTED)
        {
            return;
        }
        _send_buffer.WriteBufferAndPush(buf);
        if (!_channel.WritEnable())
        {
            _channel.OpenWriteEventMonitoring();
        }
    }
    void ReleaseInLoop()
    {
        _statu = DISCONNECTED;
        _channel.Remove();
        _socket.Close();
        if(_loop->HasTimer(_con_id))
        {
            CancelTaskInLoop();
        }

        if (_user_close_cb)
        {
            _user_close_cb(shared_from_this());
        }

        if (_server_close_cb)
        {
            _server_close_cb(shared_from_this());
        }
    }
    void ShutdownInLoop()
    {
        LOG(DEBUG,"开始调用ShutdownInLoop函数关闭连接!,fd = %d\n",_sockfd);
        _statu = DISCONNECTING;
        if (_recv_buffer.ReadAbleSize() > 0)
        {
            if(_read_cb)
            {
                _read_cb(shared_from_this(), &_recv_buffer);
            }
        }

        if (_send_buffer.ReadAbleSize() > 0)
        {
            if (!_channel.WritEnable())
            {
                _channel.OpenWriteEventMonitoring();
            }
        }
        if (_send_buffer.ReadAbleSize() == 0)
        {
            // 不能直接执行Release！！要放入队列中!
            //  ReleaseInLoop();
            Release();
        }
        return;
    }
    void UpgradeInLoop(const Any &context,
                       const ConnectedCallback_t &conn,
                       const ReadEeventCallback_t &msg,
                       const CloseUserCallback_t &closed,
                       const EventCallback_t &event)
    {
        _context = context;
        _connected_cb = conn;
        _read_cb = msg;
        _user_close_cb = closed;
        _handle_event_cb = event;
    }

public:
    Connection(uint64_t conid, int sockfd, EventLoop *loop)
        : _con_id(conid),
          _sockfd(sockfd),
          _socket(sockfd),
          _statu(CONNECTING),
          _channel(loop, sockfd),
          _loop(loop)
    {
             _channel.SetCloseCallback(std::bind(&Connection::HandleClose,this));
            _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
            _channel.SetReadCallback(std::bind(&Connection::HandlerRead, this));
            _channel.SetWriteCallback(std::bind(&Connection::HandlerWrite, this));
            _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
    }
    ~Connection() 
    {
        LOG(DEBUG,"CLOSE CONNECTION:%u\n",this);
    }

    int Fd()
    {
        return _sockfd;
    }
    // 获取连接ID
    int Id()
    {
        return _con_id;
    }
    // 是否处于CONNECTED状态
    bool IsConnected()
    {
        return (_statu == CONNECTED);
    }
    // 设置上下⽂--连接建⽴完成时进⾏调⽤
    void SetContext(const Any &context)
    {
        _context = context;
    }
    // 获取上下⽂，返回的是指针
    Any *Context()
    {
        return &_context;
    }
    void SetConnectedCallback(const ConnectedCallback_t &cb)
    {
        _connected_cb = cb;
    }
    void SetMessageCallback(const ReadEeventCallback_t &cb)
    {
        _read_cb = cb;
    }
    void SetClosedCallback(const CloseUserCallback_t &cb)
    {
        _user_close_cb = cb;
    }
    void SetAnyEventCallback(const EventCallback_t &cb)
    {
        _handle_event_cb = cb;
    }
    void SetSrvClosedCallback(const CloseServerCallback_t &cb)
    {
        _server_close_cb = cb;
    }
    // 连接建⽴就绪后，进⾏channel回调设置，启动读监控，调⽤_connected_callback
    void Established()
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
    }
    // 发送数据，将数据放到发送缓冲区，启动写事件监控
    void Send(const char *data, size_t len)
    {
        // 外界传⼊的data，可能是个临时的空间，我们现在只是把发送操作压⼊了任务池，有可能并没有被⽴即执⾏
        // 因此有可能执⾏的时候，data指向的空间有可能已经被释放了。
        Buffer buf;
        buf.WriteAndPush(data, len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
    }
    // 提供给组件使⽤者的关闭接⼝--并不实际关闭，需要判断有没有数据待处理
    void Shutdown()
    {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
    }
    void Release()
    {
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
    }
    // 启动⾮活跃销毁，并定义多⻓时间⽆通信就是⾮活跃，添加定时任务
    void EnableInactiveRelease(int sec)
    {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
    }
    // 取消⾮活跃销毁
    void CancelInactiveRelease()
    {
        _loop->RunInLoop(std::bind(&Connection::CancelInactiveRelease, this));
    }
    // 切换协议---重置上下⽂以及阶段性回调处理函数 -- ⽽是这个接⼝必须在EventLoop线程中⽴即执⾏
    // 防备新的事件触发后，处理的时候，切换任务还没有被执⾏--会导致数据使⽤原协议处理了。
    void Upgrade(const Any &context, const ConnectedCallback_t &conn, const ReadEeventCallback_t &msg,
                 const CloseUserCallback_t &closed, const EventCallback_t &event)
    {
        _loop->AssertInLoop();
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
    }
};